/*
 *  JDiv - API for Multimedia Application
 *  http://jdiv.sourceforge.net 
 *  ------------------------------------
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software 
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 */

package com.jdiv.functions;

import java.util.Iterator;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.Joint;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.jdiv.Const;
import com.jdiv.internalClasses.ProcessReserved;
import com.jdiv.kernel.JDivResources;
import com.jdiv.kernel.JDivSystem;

public class FunctionsPhysics {
	
	/**
	 * Create a physical world, you can only create one.
	 * @param gX X-axis gravity.
	 * @param gY Y-axis gravity.
	 * @param sleep Sets whether the objects of the physical world can sleep, saving CPU. But sometimes it can be not recommended.
	 */
	
	public void createWorld( float gX, float gY, boolean sleep ){
		
		if( JDivSystem.jdivScreen != null )
			JDivSystem.jdivScreen.createBox2dWorld( gX, gY, sleep );
			 
	 }
	
	/**
	 * Set the gravity of the world.
	 * @param gX X-axis gravity.
	 * @param gY Y-axis gravity.
	 */
	
	public void setWorldGravity( float gX, float gY ){
		if( JDivSystem.box2dWorld != null ){
			JDivSystem.box2dWorld.setGravity(new Vector2(gX, gY));
		}
	}
	
	/**
	 * Add polygon static to the physical world, the vertices must be added counterclockwise.
	 * @param points Points of the polygon.
	 * @return Gets the "Body" of LibGdx for physics.
	 */
	
	public Body addStaticPolygon( float [] points ){
	
	   if( JDivSystem.box2dWorld != null ){
		   
		for( int i = 0; i < points.length; i++ )
			points[i] *= Const.BOX2D_SCREEN_TO_PHYSICS; 
		   
		PolygonShape shape = new PolygonShape();
		shape.set(points);
		
		 BodyDef chainBodyDef = new BodyDef();
		 chainBodyDef.type = BodyType.StaticBody;
		 Body body = JDivSystem.box2dWorld.createBody(chainBodyDef);
		 body.createFixture(shape, 0);
		 body.setUserData(null);
		
		shape.dispose();
		
		return body;
	   }
	   
	   return null;
	}
	
	/**
	 * Add circle static to the physical world.
	 * @param centerX X Center of the circle.
	 * @param centerY Y C.enter of the circle.
	 * @param radius Radius of the circle.
	 * @return Gets the "Body" of LibGdx for physics.
	 */

	public Body addStaticCircle( float centerX, float centerY, float radius ){
		
		   if( (JDivSystem.box2dWorld != null) && (radius > 0) ){
			   
			CircleShape circleShape = new CircleShape( );
			circleShape.setPosition(new Vector2(centerX * Const.BOX2D_SCREEN_TO_PHYSICS, 
					                            centerY * Const.BOX2D_SCREEN_TO_PHYSICS));
			circleShape.setRadius(radius * Const.BOX2D_SCREEN_TO_PHYSICS);
			
			 BodyDef bodyDef = new BodyDef();
			 bodyDef.type = BodyType.StaticBody;
			 Body circleBody = JDivSystem.box2dWorld.createBody(bodyDef);
			 circleBody.createFixture(circleShape, 0);
			 circleBody.setUserData(null);
			
			circleShape.dispose();
			
			return circleBody;
		   }
		   
		   return null;
		}
	
	/**
	 * Removes all bodies and joints of the physical world.
	 */
	
	public void clearWorld(){
		
		if( JDivSystem.box2dWorld == null ) return;
		
		deleteAllJoint();

		for (Iterator<Body> iter = JDivSystem.box2dWorld.getBodies(); iter.hasNext(); ) 
		{
		     Body body = iter.next();
		     
		     if( body!=null ) {
		    	 JDivSystem.box2dWorld.destroyBody(body);   
		         body = null;     
		     }
		}
		 
	  	for( int i = 0; i < JDivResources.listProcess.listProcessP.size(); i++ )
	  	{
	  		// Obtenemos el proceso actual
	  		ProcessReserved reserved = JDivResources.listProcess.listProcessP.get(i).getReserved();
	  	    reserved.boxBody = null;
	  	}
		
	}
	
	/**
	 * Delete the specified joint.
	 * @param joint Joint to delete.
	 */
	
	public void deleteJoint( Joint joint ){
		if( (JDivSystem.box2dWorld == null) || (joint == null) ) return;
		
		JDivSystem.box2dWorld.destroyJoint(joint);
	}
	
	/**
	 * Deletes all joints.
	 */
	
	public void deleteAllJoint(){
		
		if( JDivSystem.box2dWorld == null ) return;
		
		for (Iterator<Joint> iter = JDivSystem.box2dWorld.getJoints(); iter.hasNext(); ) 
		{
		     Joint joint = iter.next();
		     
		     if( joint != null ) {
		    	 JDivSystem.box2dWorld.destroyJoint(joint);   
		    	 joint = null;     
		     }
		}	
	}

}
